package io.renren.modules.finance.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.renren.common.base.GenericServiceImpl;
import io.renren.common.exception.RRException;
import io.renren.common.utils.*;
import io.renren.modules.finance.dao.FinanceMoneyRecordDao;
import io.renren.modules.finance.entity.UserMoneyTotal;
import io.renren.modules.finance.entity.FinanceMoneyRecord;
import io.renren.modules.finance.service.FinanceMoneyRecordService;
import io.renren.modules.finance.service.UserMoneyTotalService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 收益账户变动明细表
 *
 * @author meishou
 * @date 2019-05-02 14:36:34
 */
@Service("financeMoneyRecordService")
public class FinanceMoneyRecordServiceImpl extends GenericServiceImpl<FinanceMoneyRecordDao, FinanceMoneyRecord> implements FinanceMoneyRecordService {
    @Autowired
    @Lazy
    private UserMoneyTotalService agentMoneyTotalService;

    // 定义锁对象
    private static Lock lock = new ReentrantLock();

    /**
     * APP使用，查询明细
     *
     * @param params
     * @return
     */
    @Override
    public PageUtils queryAppPage(Map<String, Object> params) {
        IPage<FinanceMoneyRecord> page = new Query<FinanceMoneyRecord>().getPage(params);
        page = baseMapper.queryAppPage(page, params);
        return new PageUtils(page);
    }

    /**
     * 查询列表,后端使用
     *
     * @param params
     * @return
     */
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        Query<FinanceMoneyRecord> query = new Query<>();
        List<FinanceMoneyRecord> agentMoneyRecordEntityList = baseMapper.queryPage(query.getPage(params), params);
        query.getPage(params).setRecords(agentMoneyRecordEntityList);
        return new PageUtils(query.getPage(params));
    }


    /**
     * 保存记录和变更余额
     *
     * @param userId
     * @param changeItem
     * @param briefing
     * @param changeAmount
     * @return
     */
    @Override
    @Transactional(rollbackFor = RRException.class)
    public boolean saveRecord(Integer channelId, Long userId, Integer changeItem, String briefing, BigDecimal changeAmount, Integer type) {
        lock.lock();
        try {
            UserMoneyTotal agentMoneyTotalEntity = agentMoneyTotalService.getByUserId(userId);

            BigDecimal before;
            //操作之后余额不能为负
            if (type == FinanceMoneyRecord.TYPE_BALANCE) {
                before = BigDecimalUtil.nullTOZero(agentMoneyTotalEntity.getBalanceIncome());
            } else if (type == FinanceMoneyRecord.TYPE_COIN) {
                before = BigDecimalUtil.nullTOZero(agentMoneyTotalEntity.getBalanceCoin());
            } else {
                return false;
            }

            BigDecimal after = before.add(changeAmount);

            if (after.compareTo(BigDecimal.ZERO) < 0) {
                throw new RRException("操作余额不能大于账户余额");
            }

            Date createTime = DateUtils.getCurrentDate();

            //添加记录
            FinanceMoneyRecord agentMoneyRecordEntity = new FinanceMoneyRecord();
            agentMoneyRecordEntity.setUserId(userId);
            agentMoneyRecordEntity.setChangeItem(changeItem);
            agentMoneyRecordEntity.setOperatorStyle(changeAmount.compareTo(BigDecimal.ZERO) >= 0 ? 1 : 0);
            agentMoneyRecordEntity.setChangeAmount(changeAmount);
            agentMoneyRecordEntity.setBeforeAmount(before);
            agentMoneyRecordEntity.setCurrentAmount(after);
            agentMoneyRecordEntity.setBriefing(briefing);
            agentMoneyRecordEntity.setType(type);
            agentMoneyRecordEntity.setChannelId(channelId);
            agentMoneyRecordEntity.setCreateTime(createTime);
            agentMoneyRecordEntity.setModifyTime(createTime);
            baseMapper.insert(agentMoneyRecordEntity);
            //修改代理的金额表
            if (type == FinanceMoneyRecord.TYPE_BALANCE) {
                agentMoneyTotalEntity.setBalanceIncome(after);
            } else {
                agentMoneyTotalEntity.setBalanceCoin(after);
            }

            if (agentMoneyRecordEntity.getOperatorStyle() == 1) {//如果是增加余额
                if (type == FinanceMoneyRecord.TYPE_BALANCE) {
                    agentMoneyTotalEntity.setTotalIncome(agentMoneyTotalEntity.getTotalIncome().add(changeAmount));
                } else {
                    agentMoneyTotalEntity.setTotalCoin(agentMoneyTotalEntity.getTotalCoin().add(changeAmount));
                }
            } else {//如果是体现
                if (type == FinanceMoneyRecord.TYPE_BALANCE) {
                    agentMoneyTotalEntity.setWithdrawTotal(agentMoneyTotalEntity.getWithdrawTotal().add(changeAmount));
                    agentMoneyTotalEntity.setWithdrawLockMoney(agentMoneyTotalEntity.getWithdrawLockMoney().add(changeAmount));
                }
            }
            agentMoneyTotalService.updateById(agentMoneyTotalEntity);

        } finally {
            lock.unlock();
        }
        return true;
    }


    @Override
    public ExcelData export(Map<String, Object> params) {
        Page<FinanceMoneyRecord> page = new Page<>(1, Integer.MAX_VALUE);
        List<FinanceMoneyRecord> agentMoneyRecordEntityList = baseMapper.queryPage(page, params);
        ExcelData data = new ExcelData();
        data.setName("代理商收入明细");
        // 设置表头
        ArrayList<String> titles = new ArrayList<>();
        titles.add("代理商");
        titles.add("手机号");
        titles.add("变更金额");
        titles.add("当前收入余额");
        titles.add("变更及说明");
        titles.add("结算时间");
        data.setTitles(titles);
        List<List<Object>> rows = new ArrayList<>();
        if (agentMoneyRecordEntityList != null && agentMoneyRecordEntityList.size() != 0) {
            for (FinanceMoneyRecord dataTemplate : agentMoneyRecordEntityList) {
                ArrayList<Object> row = new ArrayList<>();
                row.add(dataTemplate.getName());
                row.add(dataTemplate.getMobile());
                row.add(dataTemplate.getChangeAmount());
                row.add(dataTemplate.getCurrentAmount());
                row.add(dataTemplate.getBriefing());
                row.add(DateUtils.format(dataTemplate.getCreateTime(), DateUtils.DATE_TIME_PATTERN));
                rows.add(row);
            }
        }
        data.setRows(rows);
        return data;
    }

    @Override
    public List<FinanceMoneyRecord> financeIncomeLogEntityList(Integer agentId) {
        return baseMapper.inAndOut(agentId);
    }

    @Override
    public LinkedHashMap<String, Object> getIncomeDayStatistics() {
        return baseMapper.getIncomeDayStatistics();
    }

    @Override
    public LinkedHashMap<String, Object> getIncomeWeekStatistics() {
        return baseMapper.getIncomeWeekStatistics();
    }

    @Override
    public LinkedHashMap<String, Object> getIncomeMonthStatistics() {
        return baseMapper.getIncomeMonthStatistics();
    }

    @Override
    public LinkedHashMap<String, Object> getIncomeYearStatistics() {
        return baseMapper.getIncomeYearStatistics();
    }

    @Override
    public BigDecimal getYesterdayIncome() {
        return baseMapper.getYesterdayIncome();
    }

    @Override
    public BigDecimal getBeforeWeekIncome() {
        return baseMapper.getBeforeWeekIncome();
    }

    @Override
    public BigDecimal getBeforeMonthIncome() {
        return baseMapper.getBeforeMonthIncome();
    }

    @Override
    public BigDecimal getBeforeYearIncome() {
        return baseMapper.getBeforeYearIncome();
    }

    @Override
    public List<FinanceMoneyRecord> testOutInAndOutTotal() {
        return baseMapper.testOutInAndOutTotal();
    }
}
